package v2;
import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;


/**
 * @author bosc & dunoyerd
 * @version 0.1
 * @see 
 * @since version 0.1
 */
public class Vegetaux extends Entite {
	
	//TODO: Passage des données dans TypeVegetal...
	
	// Attributs
	
	/**
	 * le type du végatal (son espèce). Ceci est une énum
	 */
	private TypeVegetal monType;
	
	// Constructeurs

	/**
	 * Constructeur permettan d'obtenir un végétal
	 * 
	 * @param maSante la Santé initiale de mon végétal
	 * @param maJaugeEau la quantité d'eau de la plante
	 * @param maPosition la position de ma plante
	 * @param monType l'espece de mon végétal
	 */
	public Vegetaux(int maSante, int maJaugeEau, Position maPosition, TypeVegetal monType) {
		super(maSante, maJaugeEau, maPosition);
		this.monType = monType;
	}
	
	/**
	 * Constructeur permettant d'obtenir un végétal à partir de son espece et de la position de mon végétal
	 * NB: on crée ici un végétal ayant uen santé moyenne et un taux hydrique optimal
	 * NB2: pas utilisé à l'heure actuelle
	 * 
	 * @param maSante la Santé initiale de mon végétal
	 * @param maJaugeEau la quantité d'eau de la plante
	 * @param maPosition la position de ma plante
	 * @param monType l'espece de mon végétal
	 */
	public Vegetaux(Position maPosition, TypeVegetal monType) {
		super(monType.maxSante()/2, (monType.maxEau()+monType.minEau())/2, maPosition);
		this.monType = monType;
	}
	
	// "Getteurs"
	
	/**
	 * Retourne les parcelles favorites du végétal
	 * @return les parcelles favorites
	 */
	public HashMap obtientMesParcFav() {
		return this.monType.mesParcFav();
	}	
	
	
	/**
	 * Retourne le facteur de pompage du végétal
	 * 
	 * @return le facteur de pompage du végétal
	 */
	public int obtientFacteurPompage() {
		return this.monType.facteurPompage();
	}


	/**
	 * Retourne le maximum de graine du végétal
	 * 
	 * @return le maximum de graine du végétal
	 */
	public int obtientMaxGraine() {
		return this.monType.maxGraine();
	}

	/**
	 * Retourne le rayon de dispersion des graines du végétal
	 * @return le rayon de dispersion des graines du végétal
	 */
	public int obtientRayonDispersion() {
		return this.monType.rayonDispersion();
	}

	/**
	 * Méthode permettan de recuperer le type (espece) du végétal.
	 * 
	 * @return l'espece du végétal (enum)
	 */
	public TypeVegetal obtientMonType() {
		return this.monType;
	}
	
	//////////////
	// Méthodes //
	//////////////
	
	/**
	 * calcul le nombre de graine en fonction de la santé actuelle(ratio santé_max santé_actuelle), du nombre maximum de graine et de l'eau (ratio max_eau et jauge_eau) 
	 * 
	 * @return le nombre de graine
	 */
	public int calculNombreGraine()
	{
		return this.monType.maxGraine()*(1-((obtientMaxSante()-obtientSante())/obtientMaxSante())-(obtientMaxEau()-obtientJaugeEau())/obtientMaxEau());
	}
	
	/**
	 * calcule la nouvelle jauge d'eau du végétaux après extraction de l'eau du sol
	 * 
	 * @param quantiteEauSol
	 * 			la quantité d'eau contenue dans la sol
	 * 
	 * @return la nouvelle quantité d'eau dans le sol
	 */
	public int recupEau(int quantiteEauSol)
	{
		int quantiteEauExtraite = quantiteEauSol*obtientFacteurPompage();
		assigneJaugeEau(obtientJaugeEau() + quantiteEauExtraite); 
		return quantiteEauSol - quantiteEauExtraite;
	}

	
	/**
	 * Calcul les parcelles sur lesquelles les graines vont pouvoir se déposer
	 * 
	 * @param nbGraines
	 * @param mesParcelles
	 * 
	 * @return une Arraylist représentant les parcelles où il y a des graines
	 */
	public ArrayList<Parcelle> mesParcGraines(int nbGraines, ArrayList<Parcelle> mesParcelles)
	{
		// la probabilité qu'une graine donnée soit dans une parcelle donnée
		double probaGrainePos = nbGraines / mesParcelles.size();
		
		//On potentialise la probabilité de presence d'une graine dans chaque case.
		ArrayList<Parcelle> mesParcGraines = new ArrayList<Parcelle>();
		for (int i =0; i<mesParcelles.size(); i++)
		{
			if (Math.random() <= probaGrainePos)
			{
				mesParcGraines.add(mesParcelles.get(i));
			}
		}
		// les positions de mes graines.
		return 	mesParcGraines;
	}
	
	/**
	 * Méthode qui fait germer une graine graines. Si la graine germe alors une plante apparait dans la parcelle
	 * 
	 * @param maParcelle
	 */
	public void germGraine(Parcelle maParcelle)
	{
		// si ma parcelle fait partie des favorite et qu'il n'y a pas de plante dessus...
		if ((this.obtientMesParcFav().containsKey(maParcelle.obtientMonType().name())) && (!maParcelle.estPlante()))
		{
			maParcelle.assigneMonVegetal(new Vegetaux(maParcelle.obtientMaPosition(), this.obtientMonType()));
		}
		// Sinon --> ma graine ne pousse pas
	}
	
	/**
	 * Méthde qui éxecute la méthode germGraine sur l'Arraylist des parcelles où il y a des graines
	 * 
	 * @param mesParcelles
	 */
	public void germinationGraines(ArrayList<Parcelle> mesParcelles)
	{
		// la germination des graines dépend de quoi?
		// --> de la parcelle
		// --> d'ou l'existence d'un attibut mesParcFav dans TypeVegetal!
		
		// je gère mes parcelles distinctement
		for (int i = 0; i<mesParcelles.size();i++)
		{
			this.germGraine(mesParcelles.get(i));
		}
	}
	
	/**
	 * Méthode qui gère la reproduction des plantes
	 * 
	 * @param mesParcelles
	 */
	public void gererReproduction(ArrayList<Parcelle> mesParcelles)
	{
		// 1 - je commence par calculer le nombre de graines que ma plante va produire
		int nbGraines = this.calculNombreGraine();
		// 2 - je détermine les parcelles ou vont se trouver mes graines
		ArrayList<Parcelle> mesParcGraines = this.mesParcGraines(nbGraines,mesParcelles);
		// 3 - je fais pousser mes graines (ou avorter)
		this.germinationGraines(mesParcGraines);
	}
	
	/**
	 * Méthode qui permet à la plante de puiser l'eau sur sa parcelle
	 * 
	 * @param mesParcelles
	 */
	public void gererGainEau(ArrayList<Parcelle> mesParcelles)
	{
		// je commence par récupere la parcelle sur laquelle je suis
		Parcelle maParcelle = null;
		for (int i=0;i<mesParcelles.size();i++)
		{
			if (mesParcelles.get(i).obtientMaPosition() == this.obtientPosition())
			{
				maParcelle = mesParcelles.get(i);
			}
		}
		// ensuite, je récupere la quantité d'eau dans la parcelle
		int eauAbsorbee = this.recupEau(maParcelle.obtientTauxHygro());
		this.assigneJaugeEau(eauAbsorbee);
	}
	
	/**
	 *  gerer la plante pour 1 tour
	 * @param mesParcelles
	 */
	public void gererPlante(ArrayList<Parcelle> mesParcelles)
	{
		// que fais la plante?
		// elle pompe de l'eau
		// elle perd de l'eau
		// elle ajuste sa santé
		// elle se reproduit
		// --> certaines plantes étant pret de la mort fleurissent pour "propager leurs gènes"
		// 1 - pompage de l'eau dans le sol
		this.gererGainEau(mesParcelles);
		
		// 2 - calcul de la perte d'eau
		this.calculPerteEau(0);

		// 3 - calcul de la santé
		this.calculSanteEau();
		
		// 4 - reproduction
		
	}
	
	/**
	 * @return une chaine de caractères
	 */
	public String toString()
	{
		String myString = new String("");
		
		myString+=" mon espece: "+this.monType;
		
		return myString;
	}
}